package com.thread;

/**
 * @author :Administrator
 * @description: 创建10个线程，让他们运行，等待4秒后，10个线程会进入等待状态，主线程通过状态判断，重新通知这
 * 所有线程，他们会重新竞争锁，其他线程由于while条件均处于等待状态，t0竞争成功，然后依次t1...
 * 本示例：让线程按顺序执行
 * @create date: 2023/2/19 17:52
 */
public class OrderWaitNotifyThread {

    private static int orderNum = 0;

    public static void main(String[] args) {
        Object obj2 = new Object();
        Thread t[] = new Thread[10];
        for (int i = 0; i < 10; i++) {
            int finalI = i+1;
            t[i] = new Thread(() -> {
                try {
                    synchronized (obj2) {
                        System.out.println("name:" + Thread.currentThread().getName() + "启动，sleep 1秒");
//                    Thread.sleep(1000);
                        while (orderNum != finalI) {
                            obj2.wait();
                        }
                        for (int j = 0; j < 5; j++) {
//                        Thread.sleep(500);
                            System.out.println("name:" + Thread.currentThread().getName() + " i=" + j);
                        }
                        orderNum++;
                        obj2.notifyAll();
                    }

                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }, "t" + i);
            t[i].start();
        }
        try {
            Thread.sleep(4000);
            System.out.println("等待线程加载...");
            int count = 0;
            while (true) {
                for (int i = 0; i < t.length; i++) {
                    if (t[i].getState() == Thread.State.WAITING) {
                        count++;
                    }
                }
                if (count == 10) {
                    synchronized (obj2) {
                        orderNum = 1;
                        obj2.notifyAll();
                        System.out.println("准备呼叫偷懒的线程...");
                        break;
                    }
                }
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
